home *** CD-ROM | disk | FTP | other *** search
/ Aminet 12 / Aminet 12 (1996)(GTI - Schatztruhe)[!][Jun 1996].iso / Aminet / dev / e / eiffel.lha / flc / source / eiffel_lex.e < prev    next >
Encoding:
Text File  |  1995-12-27  |  12.3 KB  |  490 lines

  1.  
  2. -> Copyright © 1995, Guichard Damien.
  3.  
  4. -> Eiffel 3.0 lexical analyser
  5. -> ANY,NONE,INTEGER,BOOLEAN,CHARACTER,STRING,ARRAY,REAL,DOUBLE,BIT,POINTER
  6. -> are also lexical tokens to avoid illegal use of reserved words
  7.  
  8. -> TO DO :
  9. ->   'Result' should be a reserved word
  10. ->   ANY, ARRAY and Void should not be reserved words
  11. ->   REAL, DOUBLE and BIT n constants
  12.  
  13. OPT MODULE
  14.  
  15. MODULE '*errors'
  16. MODULE '*token','*entity_tree'
  17.  
  18. EXPORT ENUM LEX_ALIAS=300,LEX_ALL,LEX_AND,LEX_ANY,LEX_ARRAY,LEX_AS,LEX_BIT,
  19.   LEX_BOOLEAN,LEX_CHARACTER,LEX_CHECK,LEX_CLASS,LEX_CREATION,LEX_CURRENT,
  20.   LEX_DEBUG,LEX_DEFERRED,LEX_DO,LEX_DOUBLE,LEX_ELSE,LEX_ELSEIF,LEX_END,
  21.   LEX_ENSURE,LEX_EXPANDED,LEX_EXPORT,LEX_EXTERNAL,LEX_FALSE,LEX_FEATURE,
  22.   LEX_FROM,LEX_FROZEN,LEX_IF,LEX_IMPLIES,LEX_INDEXING,LEX_INFIX,LEX_INHERIT,
  23.   LEX_INSPECT,LEX_INTEGER,LEX_INVARIANT,LEX_IS,LEX_LIKE,LEX_LOCAL,
  24.   LEX_LOOP,LEX_NONE,LEX_NOT,LEX_OBSOLETE,LEX_OLD,LEX_ONCE,LEX_OR,
  25.   LEX_POINTER,LEX_PREFIX,LEX_REAL,LEX_REDEFINE,LEX_RENAME,LEX_REQUIRE,
  26.   LEX_RESCUE,LEX_RESULT,LEX_RETRY,LEX_SELECT,LEX_SEPARATE,LEX_STRING,
  27.   LEX_STRIP,LEX_THEN,LEX_TRUE,LEX_UNDEFINE,LEX_UNIQUE,LEX_UNTIL,
  28.   LEX_VARIANT,LEX_VOID,LEX_WHEN,LEX_XOR
  29.  
  30. EXPORT ENUM LEX_EOF=600, -> Text end reached
  31.   LEX_IDENT,    -> self.ident contains the identifier
  32.   LEX_STR,      -> self.ident contains the string
  33.   LEX_NUMERAL,  -> self.value contains the integer
  34.   LEX_CHAR      -> self.value contains the character
  35.  
  36. -> A table to perform binary search of reserved words
  37. DEF table:PTR TO entity_tree
  38.  
  39. EXPORT OBJECT eiffel_lex PUBLIC
  40.   last:INT               -> last lexical token
  41.   value:LONG             -> numeral value
  42.   ident:PTR TO CHAR      -> current identifier
  43.   line:INT               -> current line
  44. PRIVATE
  45.   text:PTR TO CHAR       -> source text
  46.   cur:PTR TO CHAR        -> current position in text
  47.   stored_cur:PTR TO CHAR -> stored position
  48.   stored_line:INT        -> stored line
  49.   stored_last:INT        -> store lexical token
  50. ENDOBJECT
  51.  
  52. -> Load a text as a lex stream
  53. PROC attach_text(name) OF eiffel_lex HANDLE
  54.   DEF handle=NIL,slen
  55.   DEF tok:PTR TO token
  56.   IF self.text THEN self.detach_text()
  57.   slen:=FileLength(name)
  58.   IF (handle:=Open(name,OLDFILE))=NIL THEN Raise(ER_SOURCEFILE)
  59.   self.text:=NewR(slen+2)
  60.   IF Read(handle,self.text,slen)<slen THEN Raise(ER_SOURCEFILE)
  61.   self.text[slen]:="\0"
  62.   self.cur:=self.text
  63.   self.line:=1
  64.   IF self.ident=NIL THEN self.ident:=String(40)
  65.   IF table=NIL
  66.     NEW table
  67.     table.add(NEW tok.create('alias',LEX_ALIAS))
  68.     table.add(NEW tok.create('all',LEX_ALL))
  69.     table.add(NEW tok.create('and',LEX_AND))
  70.     table.add(NEW tok.create('any',LEX_ANY))
  71.     table.add(NEW tok.create('array',LEX_ARRAY))
  72.     table.add(NEW tok.create('as',LEX_AS))
  73.     table.add(NEW tok.create('bit',LEX_BIT))
  74.     table.add(NEW tok.create('boolean',LEX_BOOLEAN))
  75.     table.add(NEW tok.create('character',LEX_CHARACTER))
  76.     table.add(NEW tok.create('check',LEX_CHECK))
  77.     table.add(NEW tok.create('class',LEX_CLASS))
  78.     table.add(NEW tok.create('creation',LEX_CREATION))
  79.     table.add(NEW tok.create('current',LEX_CURRENT))
  80.     table.add(NEW tok.create('debug',LEX_DEBUG))
  81.     table.add(NEW tok.create('deferred',LEX_DEFERRED))
  82.     table.add(NEW tok.create('do',LEX_DO))
  83.     table.add(NEW tok.create('double',LEX_DOUBLE))
  84.     table.add(NEW tok.create('else',LEX_ELSE))
  85.     table.add(NEW tok.create('elseif',LEX_ELSEIF))
  86.     table.add(NEW tok.create('end',LEX_END))
  87.     table.add(NEW tok.create('ensure',LEX_ENSURE))
  88.     table.add(NEW tok.create('expanded',LEX_EXPANDED))
  89.     table.add(NEW tok.create('export',LEX_EXPORT))
  90.     table.add(NEW tok.create('external',LEX_EXTERNAL))
  91.     table.add(NEW tok.create('false',LEX_FALSE))
  92.     table.add(NEW tok.create('feature',LEX_FEATURE))
  93.     table.add(NEW tok.create('from',LEX_FROM))
  94.     table.add(NEW tok.create('frozen',LEX_FROZEN))
  95.     table.add(NEW tok.create('if',LEX_IF))
  96.     table.add(NEW tok.create('implies',LEX_IMPLIES))
  97.     table.add(NEW tok.create('indexing',LEX_INDEXING))
  98.     table.add(NEW tok.create('infix',LEX_INFIX))
  99.     table.add(NEW tok.create('inherit',LEX_INHERIT))
  100.     table.add(NEW tok.create('inspect',LEX_INSPECT))
  101.     table.add(NEW tok.create('integer',LEX_INTEGER))
  102.     table.add(NEW tok.create('invariant',LEX_INVARIANT))
  103.     table.add(NEW tok.create('is',LEX_IS))
  104.     table.add(NEW tok.create('like',LEX_LIKE))
  105.     table.add(NEW tok.create('local',LEX_LOCAL))
  106.     table.add(NEW tok.create('loop',LEX_LOOP))
  107.     table.add(NEW tok.create('none',LEX_NONE))
  108.     table.add(NEW tok.create('not',LEX_NOT))
  109.     table.add(NEW tok.create('obsolete',LEX_OBSOLETE))
  110.     table.add(NEW tok.create('old',LEX_OLD))
  111.     table.add(NEW tok.create('once',LEX_ONCE))
  112.     table.add(NEW tok.create('or',LEX_OR))
  113.     table.add(NEW tok.create('pointer',LEX_POINTER))
  114.     table.add(NEW tok.create('prefix',LEX_PREFIX))
  115.     table.add(NEW tok.create('real',LEX_REAL))
  116.     table.add(NEW tok.create('redefine',LEX_REDEFINE))
  117.     table.add(NEW tok.create('rename',LEX_RENAME))
  118.     table.add(NEW tok.create('require',LEX_REQUIRE))
  119.     table.add(NEW tok.create('rescue',LEX_RESCUE))
  120.  -> table.add(NEW tok.create('result',LEX_RESULT))
  121.     table.add(NEW tok.create('retry',LEX_RETRY))
  122.     table.add(NEW tok.create('select',LEX_SELECT))
  123.     table.add(NEW tok.create('separate',LEX_SEPARATE))
  124.     table.add(NEW tok.create('string',LEX_STRING))
  125.     table.add(NEW tok.create('strip',LEX_STRIP))
  126.     table.add(NEW tok.create('then',LEX_THEN))
  127.     table.add(NEW tok.create('true',LEX_TRUE))
  128.     table.add(NEW tok.create('undefine',LEX_UNDEFINE))
  129.     table.add(NEW tok.create('unique',LEX_UNIQUE))
  130.     table.add(NEW tok.create('until',LEX_UNTIL))
  131.     table.add(NEW tok.create('variant',LEX_VARIANT))
  132.     table.add(NEW tok.create('void',LEX_VOID))
  133.     table.add(NEW tok.create('when',LEX_WHEN))
  134.     table.add(NEW tok.create('xor',LEX_XOR))
  135.   ENDIF
  136.   self.read()
  137. EXCEPT DO
  138.   IF handle THEN Close(handle)
  139.   ReThrow()
  140. ENDPROC
  141.  
  142. -> Detach the text
  143. PROC detach_text() OF eiffel_lex
  144.   Dispose(self.text)
  145.   self.text:=NIL
  146. ENDPROC
  147.  
  148. -> Read next lexical token form the text
  149. -> Update line, last, value, ident
  150. PROC read() OF eiffel_lex
  151.   DEF cur:PTR TO CHAR
  152.   cur:=self.cur
  153.   self.last:=0
  154.   REPEAT
  155.     SELECT 256 OF cur[]++
  156.     CASE ",",";","*","+","=","(",")","{","}","[","]","@","!"
  157.       self.last:=cur[-1]
  158.     CASE "a" TO "z","A" TO "Z","_"
  159.       self.cur:=cur-1
  160.       self.last:=LEX_IDENT
  161.       self.identifier()
  162.       RETURN
  163.     CASE "0" TO "9"
  164.       self.cur:=cur-1
  165.       self.last:=LEX_NUMERAL
  166.       self.number()
  167.       RETURN
  168.     CASE "\a"
  169.       self.cur:=cur
  170.       self.last:=LEX_CHAR
  171.       self.character()
  172.       RETURN
  173.     CASE "\q"
  174.       self.cur:=cur
  175.       self.last:=LEX_STR
  176.       self.string()
  177.       RETURN
  178.     CASE "-"
  179.       IF cur[]="-"
  180.         INC cur
  181.         WHILE cur[]++<>"\n" DO NOP
  182.         self.line:=self.line+1
  183.       ELSEIF cur[]=">"
  184.         INC cur
  185.         self.last:="->"
  186.       ELSE
  187.         self.last:="-"
  188.       ENDIF
  189.     CASE "."
  190.       IF cur[]="."
  191.         INC cur
  192.         self.last:=".."
  193.       ELSE
  194.         self.last:="."
  195.       ENDIF
  196.     CASE "/"
  197.       IF cur[]="/"
  198.         INC cur
  199.         self.last:="//"
  200.       ELSEIF cur[]="="
  201.         INC cur
  202.         self.last:="/="
  203.       ELSE
  204.         self.last:="/"
  205.       ENDIF
  206.     CASE ">"
  207.       IF cur[]=">"
  208.         INC cur
  209.         self.last:=">>"
  210.       ELSEIF cur[]="="
  211.         INC cur
  212.         self.last:=">="
  213.       ELSE
  214.         self.last:=">"
  215.       ENDIF
  216.     CASE "<"
  217.       IF cur[]="<"
  218.         INC cur
  219.         self.last:="<<"
  220.       ELSEIF cur[]="="
  221.         INC cur
  222.         self.last:="<="
  223.       ELSE
  224.         self.last:="<="
  225.       ENDIF
  226.     CASE ":"
  227.       IF cur[]="="
  228.         INC cur
  229.         self.last:=":="
  230.       ELSE
  231.         self.last:=":"
  232.       ENDIF
  233.     CASE "?"
  234.       IF cur[]++<>"=" THEN Raise(ER_SYNTAX)
  235.       self.last:="?="
  236.     CASE "\\"
  237.       IF cur[]++<>"\\" THEN Raise(ER_SYNTAX)
  238.       self.last:="\\\\"
  239.     CASE "\n"
  240.       self.line:=self.line+1
  241.     CASE "\0"
  242.       self.last:=LEX_EOF
  243.     CASE " ","\t","\b"
  244.     DEFAULT
  245.       Raise(ER_SYNTAX)
  246.     ENDSELECT
  247.   UNTIL self.last
  248.   self.cur:=cur
  249. ENDPROC
  250.  
  251. -> Store text position
  252. PROC store() OF eiffel_lex
  253.   self.stored_cur:=self.cur
  254.   self.stored_line:=self.line
  255.   self.stored_last:=self.last
  256. ENDPROC
  257.  
  258. -> Restore text position
  259. PROC restore() OF eiffel_lex
  260.   self.cur :=self.stored_cur
  261.   self.line:=self.stored_line
  262.   self.last:=self.stored_last
  263. ENDPROC
  264.  
  265. -> Destructor
  266. PROC end() OF eiffel_lex
  267.   IF self.text THEN self.detach_text()
  268.   IF self.ident THEN DisposeLink(self.ident)
  269. ENDPROC
  270.  
  271.  
  272. -> PRIVATE methods used by read()
  273.  
  274. -> Find reserved word if possible
  275. PROC identifier() OF eiffel_lex
  276.   DEF c:PTR TO CHAR,cur,a
  277.   DEF tok:PTR TO token
  278.   c:=self.ident
  279.   cur:=self.cur
  280.   WHILE self.isalpha(a:=cur[]++) OR self.isdigit(a) DO c[]++:=a
  281.   c[]:="\0"
  282.   LowerStr(self.ident)
  283.   self.cur:=cur-1
  284.   IF tok:=table.find(self.ident) THEN self.last:=tok.type
  285. ENDPROC
  286.  
  287. -> Parse eiffel integers and these nasty "_"
  288. PROC number() OF eiffel_lex
  289.   DEF c,cur,value=0
  290.   cur:=self.cur
  291.   c:=cur[]
  292.   WHILE self.isdigit(c)
  293.     IF c="_"
  294.       WHILE cur[]="_"
  295.         self.cur:=cur+1
  296.         value:=Mul(1000,value)+self.digits()
  297.         cur:=cur+4
  298.       ENDWHILE
  299.       self.value:=value
  300.       RETURN
  301.     ELSE
  302.       value:=Mul(10,value)+c-"0"
  303.     ENDIF
  304.     INC cur
  305.     c:=cur[]
  306.   ENDWHILE
  307.   self.cur:=cur
  308.   self.value:=value
  309. ENDPROC
  310.  
  311. -> Parse 3 Eiffel digits
  312. PROC digits() OF eiffel_lex
  313.   DEF c,i,value=0
  314.   FOR i:=1 TO 3
  315.     c:=self.cur[]
  316.     self.cur:=self.cur+SIZEOF CHAR
  317.     IF Not(self.isdigit(c)) THEN Raise(ER_SYNTAX)
  318.     IF c="_" THEN Raise(ER_SYNTAX)
  319.     value:=10*value+c-"0"
  320.   ENDFOR
  321. ENDPROC value
  322.  
  323. -> In future "_" won't be considered as a real Eiffel digit
  324. PROC isdigit(c) OF eiffel_lex
  325. ENDPROC (c>="0") AND (c<="9") OR (c="_")
  326.  
  327. -> More classic alpha characters
  328. PROC isalpha(c) OF eiffel_lex
  329.  IF c="_" THEN RETURN TRUE
  330.  IF (c>="a") AND (c<="z") THEN RETURN TRUE
  331.  IF (c>="A") AND (c<="Z") THEN RETURN TRUE
  332. ENDPROC
  333.  
  334. -> Eiffel strings with all special characters
  335. PROC string() OF eiffel_lex
  336.   DEF c:PTR TO CHAR,a
  337.   c:=self.ident
  338.   LOOP
  339.     a:=self.cur[]
  340.     self.cur:=self.cur+1
  341.     SELECT a
  342.     CASE "\q"
  343.       c[]:="\0"
  344.       RETURN
  345.     CASE "%"
  346.       a:=self.cur[]
  347.       self.cur:=self.cur+1
  348.       SELECT a
  349.       CASE "A"
  350.         c[]++:="@"
  351.       CASE "B"
  352.         c[]++:=8
  353.       CASE "C"
  354.         c[]++:="^"
  355.       CASE "D"
  356.         c[]++:="$"
  357.       CASE "F"
  358.         c[]++:=12
  359.       CASE "H"
  360.         c[]++:="\\"
  361.       CASE "L"
  362.         c[]++:="~"
  363.       CASE "N"
  364.         c[]++:="\n"
  365.       CASE "Q"
  366.         c[]++:="`"
  367.       CASE "R"
  368.         c[]++:="\b"
  369.       CASE "S"
  370.         c[]++:="#"
  371.       CASE "T"
  372.         c[]++:="\t"
  373.       CASE "U"
  374.         c[]++:="\0"
  375.       CASE "V"
  376.         c[]++:="|"
  377.       CASE "%"
  378.         c[]++:="%"
  379.       CASE "\a"
  380.         c[]++:="\a"
  381.       CASE "\q"
  382.         c[]++:="\q"
  383.       CASE "("
  384.         c[]++:="["
  385.       CASE ")"
  386.         c[]++:="]"
  387.       CASE "<"
  388.         c[]++:="{"
  389.       CASE ">"
  390.         c[]++:="}"
  391.       CASE "/"
  392.         self.value:=Val(self.cur,{a})
  393.         IF a=0 THEN Raise(ER_SYNTAX)
  394.         c[]++:=self.value
  395.         self.cur:=self.cur+a
  396.         IF self.cur[]<>"/" THEN Raise(ER_SYNTAX)
  397.         self.cur:=self.cur+1
  398.       DEFAULT
  399.         Raise(ER_SYNTAX)
  400.       ENDSELECT
  401.     CASE "\0"
  402.       Raise(ER_SYNTAX)
  403.     CASE "\a"
  404.       Raise(ER_SYNTAX)
  405.     CASE "\b"
  406.       Raise(ER_SYNTAX)
  407.     CASE "\n"
  408.       Raise(ER_SYNTAX)
  409.     DEFAULT
  410.       c[]++:=a
  411.     ENDSELECT
  412.   ENDLOOP
  413. ENDPROC
  414.  
  415. -> Eiffel characters without special characters
  416. PROC character() OF eiffel_lex
  417.   DEF a,len
  418.   a:=self.cur[]
  419.   self.cur:=self.cur+1
  420.   SELECT a
  421.   CASE "%"
  422.     a:=self.cur[]
  423.     self.cur:=self.cur+1
  424.     SELECT a
  425.     CASE "A"
  426.       a:="@"
  427.     CASE "B"
  428.       a:=8
  429.     CASE "C"
  430.       a:="^"
  431.     CASE "D"
  432.       a:="$"
  433.     CASE "F"
  434.       a:=12
  435.     CASE "H"
  436.       a:="\\"
  437.     CASE "L"
  438.       a:="~"
  439.     CASE "N"
  440.       a:="\n"
  441.     CASE "Q"
  442.       a:="`"
  443.     CASE "R"
  444.       a:="\b"
  445.     CASE "S"
  446.       a:="#"
  447.     CASE "T"
  448.       a:="\t"
  449.     CASE "U"
  450.       a:="\0"
  451.     CASE "V"
  452.       a:="|"
  453.     CASE "%"
  454.       a:="%"
  455.     CASE "\a"
  456.       a:="\a"
  457.     CASE "\q"
  458.       a:="\q"
  459.     CASE "("
  460.       a:="["
  461.     CASE ")"
  462.       a:="]"
  463.     CASE "<"
  464.       a:="{"
  465.     CASE ">"
  466.       a:="}"
  467.     CASE "/"
  468.       a:=Val(self.cur,{len})
  469.       IF len=0 THEN Raise(ER_SYNTAX)
  470.       self.cur:=self.cur+len
  471.       IF self.cur[]<>"/" THEN Raise(ER_SYNTAX)
  472.       self.cur:=self.cur+1
  473.     DEFAULT
  474.       Raise(ER_SYNTAX)
  475.     ENDSELECT
  476.   CASE "\0"
  477.     Raise(ER_SYNTAX)
  478.   CASE "\a"
  479.     Raise(ER_SYNTAX)
  480.   CASE "\b"
  481.     Raise(ER_SYNTAX)
  482.   CASE "\n"
  483.     Raise(ER_SYNTAX)
  484.   ENDSELECT
  485.   self.value:=a
  486.   IF self.cur[]<>"\a" THEN Raise(ER_SYNTAX)
  487.   self.cur:=self.cur+1
  488. ENDPROC
  489.  
  490.